import projectConfig from '../core/config';
import JSEncrypt from '../static/jsencrypt.js';

const dayjs = require('dayjs')

const publicKey = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCpC4QMnbTrQOFriJJCCFFWhlruBJThAEBfRk7pRx1jsAhyNVL3CqJb0tRvpnbCnJhrRAEPdgFHXv5A0RrvFp+5Cw7QoFH6O9rKB8+0H7+aVQeKITMUHf/XMXioymw6Iq4QfWd8RhdtM1KM6eGTy8aU7SO2s69Mc1LXefg/x3yw6wIDAQAB';

export function encrypt(value) {
  if (value == null || value === '') return null;
  let encrypt = new JSEncrypt();
  encrypt.setPublicKey(publicKey);
  return encodeURIComponent(encrypt.encrypt(value));
}

export function getToken() {
  return uni.getStorageSync('token');
}

export function setToken(token) {
  if (token == null || token === '') {
    uni.removeStorageSync('token');
  } else {
    uni.setStorageSync('token', token);
  }
}

export function getAppId() {
  let appId = uni.getStorageSync('appId');
  return appId != null ? appId : undefined;
}

export function setAppId(appId) {
  if (appId == null || appId === '') {
    uni.removeStorageSync('appId');
  } else {
    uni.setStorageSync('appId', appId);
  }
}

export function treeDataTranslate(data, id = 'id', pid = 'parentId') {
  var res = []
  var temp = {}
  for (var i = 0; i < data.length; i++) {
    temp[data[i][id]] = data[i]
  }
  for (var k = 0; k < data.length; k++) {
    if (temp[data[k][pid]] && data[k][id] !== data[k][pid]) {
      if (!temp[data[k][pid]]['children']) {
        temp[data[k][pid]]['children'] = []
      }
      if (!temp[data[k][pid]]['_level']) {
        temp[data[k][pid]]['_level'] = 1
      }
      data[k]['_level'] = temp[data[k][pid]]._level + 1
      data[k]['_parent'] = data[k][pid]
      temp[data[k][pid]]['children'].push(data[k])
    } else {
      res.push(data[k])
    }
  }

  return res
}

export function setObjectToSessionStorage(key, value) {
  if (key == null || key === '') return false;
  if (value == null) {
    uni.removeStorageSync(key);
    return true;
  } else {
    try {
      uni.setStorageSync(key, JSON.stringify({
        data: value
      }));
      return true;
    } catch (e) {
      return false;
    }
  }
}

export function getObjectFromSessionStorage(key) {
  if (key == null || key === '') return null;
  try {
    let jsonObj = uni.getStorageSync(key);
    if (jsonObj != null && jsonObj !== '') {
      jsonObj = JSON.parse(jsonObj);
      return (jsonObj || {}).data;
    }
  } catch (e) {
    return null;
  }
}

export function objectToQueryString(params) {
  if (params == null) {
    return null;
  } else {
    return Object.keys(params).map((key) => {
      if (params[key] !== undefined) {
        return `${key}=${params[key]}`;
      } else {
        return undefined;
      }
    }).filter(item => item != null).join('&');
  }
}

export function getHeadImageUrl(userInfo) {
  if (userInfo == null || userInfo.headImageUrl == null) return null;
  let url, params;
  try {
    url = JSON.parse(userInfo.headImageUrl);
    const token = uni.getStorageSync('token')
    if (Array.isArray(url)) {
      url = url[0];
      params = {
        filename: url.filename,
        Authorization: token
      };
      url = url.downloadUri;
    } else {
      url = null;
    }
  } catch (e) {
    url = null;
  }
  if (url != null) {
    url = buildGetUrl(url, params);
  }
  return url;
}

export function buildGetUrl(actionName, params) {
  let queryString = objectToQueryString(params);
  if (actionName != null && actionName !== '') {
    if (actionName.substr(0, 1) === '/') actionName = actionName.substr(1);
  }

  if (actionName.indexOf('http://') === 0 || actionName.indexOf('https://') === 0) {
    return actionName + (queryString == null ? '' : ('?' + queryString));
  } else {
    return projectConfig.baseUrl + actionName + (queryString == null ? '' : ('?' + queryString));
  }
}

export function formatDate(date, formatString) {
  return dayjs(date).format(formatString)
}

/**
 * 从数组中查找某一项
 * @param {Array} list 要查找的数组
 * @param {String} id 要查找的节点id
 * @param {String} idKey 主键字段名（如果为null则直接比较）
 * @param {Boolean} removeItem 是否从数组中移除查找到的节点
 * @returns {Object} 找到返回节点，没找到返回undefined
 */
export function findItemFromList(list, id, idKey, removeItem = false) {
  if (Array.isArray(list) && list.length > 0 && ( id != null || id != undefined)) {
    if (Array.isArray(id)) {
      let idSet = new Set();
      id.forEach(item => {
        idSet.add(item);
      });
      let tempList = list.filter(item => {
        return idSet.has(item[idKey]);
      });
      idSet = null;
      return tempList;
    } else {
      for (let i = 0; i < list.length; i++) {
        let item = list[i];
        if (((idKey == null || idKey === '') && item === id) || (idKey != null && item[idKey] === id)) {
          if (removeItem) list.splice(i, 1);
          return item;
        }
      }
    }
  }
  return null;
}

export function megerList(list1, list2, idKey = 'id') {
  let temp = {};
  if (idKey != null && idKey !== '') {
    if (Array.isArray(list1)) {
      list1.forEach(item => {
        temp[item[idKey]] = item;
      });
    }
    if (Array.isArray(list2)) {
      list2.forEach(item => {
        temp[item[idKey]] = item;
      });
    }
  }
  return Object.keys(temp).reduce((retObj, key) => {
    if (temp[key] != null) {
      retObj.push(temp[key]);
    }
    return retObj;
  }, []);
}

/**
 * 通过id从树中获取指定的节点
 * @param {Object} node 根节点
 * @param {String|Nubmer} id 键值
 * @param {Array} list 保存查询路径
 * @param {String} idKey 主键字段名
 * @param {String} childKey 子节点字段名
 */
function findNode(node, id, list, idKey = 'id', childKey = 'children') {
  if (Array.isArray(list)) list.push(node);
  if (node[idKey] === id) {
    return node;
  }

  if (node[childKey] != null && Array.isArray(node[childKey])) {
    for (let i = 0; i < node[childKey].length; i++) {
      let tempNode = findNode(node[childKey][i], id, list, idKey, childKey);
      if (tempNode) return tempNode;
    }
  }

  if (Array.isArray(list)) list.pop();
}

/**
 * 通过id返回从根节点到指定节点的路径
 * @param {Array} treeRoot 树根节点数组
 * @param {*} id 要查询的节点的id
 * @param {*} idKey 主键字段名
 * @param {*} childKey 子节点字段名
 */
export function findTreeNodeObjectPath(treeRoot, id, idKey = 'id', childKey = 'children') {
  let tempList = [];
  for (let i = 0; i < treeRoot.length; i++) {
    if (findNode(treeRoot[i], id, tempList, idKey, childKey)) {
      return tempList;
    }
  }

  return [];
}

/**
 * 通过id从树中查找节点
 * @param {Array} treeRoot 根节点数组
 * @param {*} id 要查找的节点的id
 * @param {*} idKey 主键字段名
 * @param {*} childKey 子节点字段名
 */
export function findTreeNode(treeRoot, id, idKey = 'id', childKey = 'children') {
  for (let i = 0; i < treeRoot.length; i++) {
    let tempNode = findNode(treeRoot[i], id, undefined, idKey, childKey);
    if (tempNode) return tempNode;
  }
}

// 深度遍历树节点
export function traverseTree(root, callback, childKey = 'children') {
  function traverseNode(node) {
    if (typeof callback === 'function') callback(node);
    if (Array.isArray(node[childKey])) {
      node[childKey].forEach(suNode => {
        traverseNode(suNode);
      });
    }
  }

  if (Array.isArray(root)) {
    root.forEach(node => {
      traverseNode(node);
    });
  }
}

/**
 * 大小驼峰变换函数
 * @param name 要转换的字符串
 * @param type 转换的类型0：转换成小驼峰，1：转换成大驼峰
 */
export function nameTranslate(name, type) {
  name = name.toLowerCase();
  let nameArray = name.split('_');
  nameArray.forEach((item, index) => {
    if (index === 0) {
      name = type === 1 ? item.slice(0, 1).toUpperCase() + item.slice(1) : item;
    } else {
      name = name + item.slice(0, 1).toUpperCase() + item.slice(1);
    }
  });

  nameArray = name.split('-');
  nameArray.forEach((item, index) => {
    if (index === 0) {
      name = type === 1 ? item.slice(0, 1).toUpperCase() + item.slice(1) : item;
    } else {
      name = name + item.slice(0, 1).toUpperCase() + item.slice(1);
    }
  });
  return name;
}

export function getBoundingClientRect(windowWidth, statusBarHeight) {
  let rect = {
    top: 25,
    left: 0,
    width: windowWidth,
    height: statusBarHeight,
    isType: 'H5'
  }
  // #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-QQ
  if (wx && typeof wx.getMenuButtonBoundingClientRect == 'function') {
    let rect0 = wx.getMenuButtonBoundingClientRect()
    if (rect0) {
      rect0.isType = 'WX'
      rect = rect0
    }
  }
  // #endif
  return rect
}

export function isObject(obj) {
  return obj != null && typeof obj === 'object' && Array.isArray(obj) === false;
}


function copyObject(obj) {
  if (obj == null) return obj;
  if (Array.isArray(obj)) {
    return obj.map(item => {
      return copyObject(item);
    });
  } else if (isObject(obj)) {
    return Object.keys(obj).reduce((tempObj, key) => {
      tempObj[key] = copyObject(obj[key]);
      return tempObj;
    }, {});
  } else {
    return obj;
  }
}

export function deepMerge(obj1, obj2) {
  const tempObj = copyObject(obj1);
  if (obj2 != null) {
    Object.keys(obj2).forEach(key => {
      const val2 = obj2[key];
      const val1 = tempObj[key];
      console.log(key, val1, val2);
      if (isObject(val2)) {
        // 如果两个值都是对象，则递归合并
        if (isObject(val1)) {
          tempObj[key] = deepMerge(val1, val2);
        } else {
          tempObj[key] = copyObject(val2);
        }
      } else if (Array.isArray(val2)) {
        // 如果两个值都是数组，则合并数组
        if (Array.isArray(val1)) {
          tempObj[key] = val2.map((arrVal2, index) => {
            const arrVal1 = val1[index];
            return deepMerge(arrVal1, arrVal2);
          });
        } else {
          console.log(key, val2);
          tempObj[key] = copyObject(val2);
        }
      } else {
        // 直接覆盖
        tempObj[key] = val2;
      }
    });
  }
  return tempObj;
}


// 判断数据类型
function getDataType(data) {
  const temp = Object.prototype.toString.call(data);
  const type = temp.match(/\b\w+\b/g);
  return (type.length < 2) ? 'Undefined' : type[1];
}

// 判断两个对象是否相等
export function isObjectChanged(source, comparison) {
  const iterable = (data) => ['Object', 'Array'].includes(getDataType(data));
  if (!iterable(source)) {
    throw new Error(`source should be a Object or Array , but got ${getDataType(source)}`);
  }

  if (getDataType(source) !== getDataType(comparison)) {
    return true;
  }

  const sourceKeys = Object.keys(source);

  const comparisonKeys = Object.keys({...source, ...comparison});

  if (sourceKeys.length !== comparisonKeys.length) {
    return true;
  }

  return comparisonKeys.some(key => {
    if (iterable(source[key])) {
      return isObjectChanged(source[key], comparison[key]);
    } else {
      return source[key] !== comparison[key];
    }
  });
}

export function isRequired(rulesItem) {
  if (rulesItem) {
    if (rulesItem instanceof Array) {
      let required = false
      for (let i = 0; i < rulesItem.length; i++) {
        if (rulesItem[i].required) {
          required = rulesItem[i].required
          break
        }
      }
      return required
    } else {
      return rulesItem.required || false
    }
  } else {
    return false
  }
}

export function showConfirm(content, title = '提示') {
  return new Promise((resolve, reject) => {
    uni.showModal({
      title: title,
      content: content,
      success: function(res) {
        if (res.confirm) {
          resolve();
        } else {
          resolve();
        }
      },
      fail: function() {
        resolve();
      }
    });
  });
}

export function showMessage(title, type = 'none') {
  return new Promise((resolve, reject) => {
    uni.showToast({
      title: title,
      icon: type,
      duration: 2000,
      success: function() {
        resolve();
      },
      fail: function() {
        resolve();
      }
    });
  });
}
